// 对函数防抖功能进行封装 => 可以实现对某个特定功能进行防抖处理
// callback => 需要做防抖处理的函数
export function debounce(callback,delay=0){   // 闭包 
    var timer = null;  // 减少全局变量的使用
    return function(){  // 此函数才是返回的新函数 (有自己的this指向, 可以接收参数arguments)
        // 新函数的this和arguments
        // console.log("this",this);  //
        // console.log("arguments",arguments);
        clearTimeout(timer); // 如果300ms内连续触发 => 先清除上一次,在启动下一次
        timer = setTimeout(()=>{ // 延迟300ms后开始 
            //  执行的内容 (从开始到执行 需要 300s) -> 不能定死(不同的功能 要处理的内容不一样) ->接收回调函数(用户根据自己的需要决定执行的内容) 

            // 处理 将新函数接收的this指向和接收的参数 原封不动的传递给callback(回调函数)
            callback.apply(this,arguments);  // callback 的this依赖于新函数的this指向 ,callback如果需要接收参数,依赖于新函数的arguments   (此处使用箭头函数 -> this h和arguments都访问的父作用域 !!!!)
            // callback.call(this,...arguments);   // 展开arguments => 依次传入
        },delay)
    }
}


// 对函数节流功能进行封装 => 可以实现对某个特定功能进行节流处理
//  callback 需要做节流处理的函数(原函数)
export function throttle(callback,dur = 0){
    var start = Date.now();  // 获取当前时间对应的毫秒数(页面加载时)
    return function(){
        console.log("新函数");
        // console.log("新函数",this);
        // console.log("新函数",arguments);
        var now = Date.now(); // 事件触发时的当前时间
        if(now - start > dur){
            //  执行的内容 (从开始到执行 超出 300ms,如果没有超出300ms不执行)
            callback.apply(this,arguments);
            
            start = now; // 本次执行完毕, start=记录本次的时间 ,下次要比本次还要多 300s
        }
    }
}



export function validate(reg,str){
    return reg.test(str);
}


export function currying(callback) {
    var len = callback.length; // 传入的回调函数需要接收的参数个数
    if (len > 0) { // 有至少一个参数  => 已知需要接收几个参数
        var _args = []; // 用于存放所有参数(闭包)
        return function () { // 
            _args.push(...arguments); // Array.prototype.push.apply(_args,arguments);
            if (_args.length >= len) {  // 参数已经够了,多传也没有用 => 执行传入的回调函数
                console.log("最后一层", _args);
                // return callback(..._args);  // 如果参数传入完毕 => 调用原函数
                return callback.apply(null, _args);  // 如果参数传入完毕 => 调用原函数
            }else{
                return arguments.callee;
            }
        }
    } else {
        return function () { // 
            var _args = [...arguments]; // 用于存放所有参数(闭包)
            function func() {
                _args.push(...arguments);
                return func;
            }
            // func隐式转字符串时调用   
            func.toString = func.valueOf = function () {
                // console.log("隐式转字符串", _args);
                // console.log("隐式转字符串", callback(..._args));
                return callback(..._args);  // 计算最终的结果
                // return callback.apply(null,_args);
            }
            return func;
        }
    }
}



// 单例封装  => 传入一个构造函数,将其转化为单例模式
export function singleton(fn){  // 要求接收一个函数作为构造函数
    var instance = null;
    return function(){
        if(!instance){
            instance = new fn(...arguments);
        }
        return instance;
    }
}

